﻿using System;
using System.Linq;
using System.Linq.Expressions;
using FoodBank.Core;
using FoodBank.Web.Helpers;
using Newtonsoft.Json.Linq;

namespace FoodBank.Web
{
    public static class FoodBankExceptionExtensions
    {
        public static JObject GetErrorAsJsonObject(this FoodBankException exception)
        {
            var errors = new JObject();
            if (exception.Errors.Any())
            {
                foreach (var pair in exception.Errors)
                {
                    errors.Add(pair.Key, pair.Value);
                }
            }
            else
            {
                errors.Add("serious", exception.Message);
            }
            return errors;
        }

        public static FoodBankException AsFeedBackError(this FoodBankException exception, FeedBackType feedBackType)
        {
            string feedBackAsString;
            switch (feedBackType)
            {
                case FeedBackType.Success:
                    feedBackAsString = "success";
                    break;
                case FeedBackType.Serious:
                    feedBackAsString = "serious";
                    break;
                case FeedBackType.Warning:
                    feedBackAsString = "warning";
                    break;
                case FeedBackType.Information:
                    feedBackAsString = "info";
                    break;
                default:
                    feedBackAsString = string.Empty;
                    break;
            }
            exception.Errors.Add(string.IsNullOrEmpty(feedBackAsString) ? "serious" : feedBackAsString, exception.Message);
            return exception;
        }

        public static FoodBankException For<T>(this FoodBankException exception, Expression<Func<T, object>> expression)
        {
            var memberInfo = GetMemberInfo(expression);
            var propertyName = memberInfo.Member.Name;

            if (string.IsNullOrEmpty(propertyName))
            {
                exception.AsFeedBackError(FeedBackType.Serious);
            }
            else
            {
                exception.Errors.Add(propertyName, exception.Message);
            }
            return exception;
        }

        private static MemberExpression GetMemberInfo(Expression method)
        {
            var lambda = method as LambdaExpression;
            if (lambda == null)
                throw new ArgumentNullException("method");

            MemberExpression memberExpr = null;

            if (lambda.Body.NodeType == ExpressionType.Convert)
            {
                memberExpr =
                    ((UnaryExpression)lambda.Body).Operand as MemberExpression;
            }
            else if (lambda.Body.NodeType == ExpressionType.MemberAccess)
            {
                memberExpr = lambda.Body as MemberExpression;
            }

            if (memberExpr == null)
                throw new ArgumentException("method");

            return memberExpr;
        }
    }
}